using Microsoft.EntityFrameworkCore;
using FServer.Core.Entities;
using FServer.Core.Interfaces;
using FServer.Infrastructure.Data;

namespace FServer.Infrastructure.Services;

/// <summary>
/// 游戏服务器管理服务实现
/// </summary>
public class GameServerService : IGameServerService
{
    private readonly GameDbContext _context;
    private readonly ILogger<GameServerService> _logger;

    public GameServerService(GameDbContext context, ILogger<GameServerService> logger)
    {
        _context = context;
        _logger = logger;
    }

    public async Task<List<GameServer>> GetServerListAsync(string? region = null, string? serverType = null)
    {
        var query = _context.GameServers
            .Where(s => s.IsEnabled && s.Status == "Online");

        if (!string.IsNullOrEmpty(region))
        {
            query = query.Where(s => s.Region == region);
        }

        if (!string.IsNullOrEmpty(serverType))
        {
            query = query.Where(s => s.ServerType == serverType);
        }

        var servers = await query
            .OrderBy(s => s.LoadPercentage)
            .ThenBy(s => s.Name)
            .ToListAsync();

        // 更新繁忙程度
        foreach (var server in servers)
        {
            server.BusyLevel = CalculateBusyLevel(server.LoadPercentage, server.CurrentConnections, server.MaxConnections);
        }

        _logger.LogInformation("获取服务器列表: {Count} 个服务器", servers.Count);
        return servers;
    }

    public async Task<GameServer?> GetRecommendedServerAsync(string? region = null)
    {
        var query = _context.GameServers
            .Where(s => s.IsEnabled && s.Status == "Online" && s.IsRecommended);

        if (!string.IsNullOrEmpty(region))
        {
            query = query.Where(s => s.Region == region);
        }

        var server = await query
            .OrderBy(s => s.LoadPercentage)
            .FirstOrDefaultAsync();

        if (server != null)
        {
            server.BusyLevel = CalculateBusyLevel(server.LoadPercentage, server.CurrentConnections, server.MaxConnections);
        }

        _logger.LogInformation("获取推荐服务器: {ServerName}", server?.Name);
        return server;
    }

    public async Task<GameServer?> GetServerAsync(Guid serverId)
    {
        var server = await _context.GameServers
            .FirstOrDefaultAsync(s => s.Id == serverId);

        if (server != null)
        {
            server.BusyLevel = CalculateBusyLevel(server.LoadPercentage, server.CurrentConnections, server.MaxConnections);
        }

        return server;
    }

    public async Task<bool> UpdateServerStatusAsync(Guid serverId, string status, int currentConnections, int loadPercentage)
    {
        try
        {
            var server = await _context.GameServers
                .FirstOrDefaultAsync(s => s.Id == serverId);

            if (server == null)
            {
                _logger.LogWarning("服务器不存在: {ServerId}", serverId);
                return false;
            }

            server.Status = status;
            server.CurrentConnections = currentConnections;
            server.LoadPercentage = loadPercentage;
            server.BusyLevel = CalculateBusyLevel(loadPercentage, currentConnections, server.MaxConnections);
            server.LastHeartbeat = DateTime.UtcNow;
            server.UpdatedAt = DateTime.UtcNow;

            await _context.SaveChangesAsync();

            _logger.LogInformation("更新服务器状态: {ServerName}, 状态: {Status}, 连接数: {Connections}, 负载: {Load}%", 
                server.Name, status, currentConnections, loadPercentage);

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新服务器状态失败: {ServerId}", serverId);
            return false;
        }
    }

    public async Task<GameServer> RegisterServerAsync(GameServer server)
    {
        server.CreatedAt = DateTime.UtcNow;
        server.UpdatedAt = DateTime.UtcNow;
        server.LastHeartbeat = DateTime.UtcNow;

        _context.GameServers.Add(server);
        await _context.SaveChangesAsync();

        _logger.LogInformation("注册新服务器: {ServerName} ({ServerId})", server.Name, server.ServerId);
        return server;
    }

    public async Task<bool> UnregisterServerAsync(Guid serverId)
    {
        try
        {
            var server = await _context.GameServers
                .FirstOrDefaultAsync(s => s.Id == serverId);

            if (server == null)
            {
                _logger.LogWarning("服务器不存在: {ServerId}", serverId);
                return false;
            }

            server.Status = "Offline";
            server.UpdatedAt = DateTime.UtcNow;

            await _context.SaveChangesAsync();

            _logger.LogInformation("注销服务器: {ServerName}", server.Name);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "注销服务器失败: {ServerId}", serverId);
            return false;
        }
    }

    public async Task<bool> HeartbeatAsync(Guid serverId)
    {
        try
        {
            var server = await _context.GameServers
                .FirstOrDefaultAsync(s => s.Id == serverId);

            if (server == null)
            {
                _logger.LogWarning("服务器不存在: {ServerId}", serverId);
                return false;
            }

            server.LastHeartbeat = DateTime.UtcNow;
            server.UpdatedAt = DateTime.UtcNow;

            await _context.SaveChangesAsync();

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "服务器心跳失败: {ServerId}", serverId);
            return false;
        }
    }

    /// <summary>
    /// 计算服务器繁忙程度
    /// </summary>
    private string CalculateBusyLevel(int loadPercentage, int currentConnections, int maxConnections)
    {
        var connectionRatio = (double)currentConnections / maxConnections;
        
        if (loadPercentage >= 90 || connectionRatio >= 0.9)
            return "Full";
        else if (loadPercentage >= 70 || connectionRatio >= 0.7)
            return "High";
        else if (loadPercentage >= 40 || connectionRatio >= 0.4)
            return "Medium";
        else
            return "Low";
    }
}
